﻿//------------------------------------------------------------------
// System Name:    NRemedy
// Component:      NRemedy
// Create by:      Parker Zhou (parkerz@wicresoft.com)
// Create Date:    2012-04-10
//------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using BMC.ARSystem;
using System.Text;

namespace Wicresoft.EKA.NRemedy
{
    /// <summary>
    /// ARProxy
    /// </summary>
    /// <example>
    /// <code>
    /// 
    ///GlobalSettings.SetCharacterEncoding("UTF8");    //GlobalSetting 里面 
    ///
    ///string ARServer = ConfigurationManager.AppSettings["ARServer"];
    ///string ARUid = ConfigurationManager.AppSettings["ARUid"];
    ///string ARPwd = ConfigurationManager.AppSettings["ARPwd"];
    ///ARLoginContext context = new ARLoginContext(ARServer, ARUid, ARPwd);
    ///ARProxy&lt;Rack&gt;  rack = new ARProxy&lt;Rack&gt; (context);
    ///string querystr = string.Format("\'InstanceId\'=\"{0}\"", instanceId.Text);
    ///Rack ra = rack.GetEntryByQuery(querystr)[0];
    ///ra.Loaction="rack_Location"
    ///rack.SetEntry(ra); 
    ///</code>
    /// </example>
    /// <typeparam name="T">Type</typeparam>
    public class ARProxy<T> where T : ARBaseForm
    {
        protected ARLoginContext loginContext;

        /// <summary>
        /// Constructor 1 
        /// </summary>
        /// <!--William Wang-->
        /// <param name="context">LoginContext</param>
        /// <param name="factory">Server Factory</param>
        public ARProxy(ARLoginContext context)
        {
            if (context == null) throw new ArgumentNullException("context");
            if (string.IsNullOrWhiteSpace(context.Server)) throw new ArgumentNullException("context.Server");
            if (string.IsNullOrWhiteSpace(context.User)) throw new ArgumentNullException("context.User");
            if (string.IsNullOrWhiteSpace(context.Password)) throw new ArgumentNullException("context.Password");
            loginContext = context;
        }

        /// <summary>
        /// Create AR Entry by model, and indicate modelbinder、FormNameUtil
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entry">model</param>
        public string CreateEntry(T entry)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            return loginContext.ServerInstance.CreateEntry(entry.FormName, entry.ValueList);
        }

        /// <summary>
        /// Create list entry
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entries">List Model</param>
        public void CreateListEntry(IList<T> entries)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");

            foreach (T item in entries)
            {
                loginContext.ServerInstance.CreateEntry(item.FormName, item.ValueList);
            }

        }

        /// <summary>
        /// Delete AR Entry by model, and indicate modelbinder、FormNameUtil
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entry">model</param>
        public void DeleteEntry(T entry)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            loginContext.ServerInstance.DeleteEntry(entry.FormName, entry.ValueList[1], 0);
        }

        /// <summary>
        /// Delete list entry
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entries">List Model</param>
        public void DeleteListEntry(IList<T> entries)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");

            StringBuilder ids = new StringBuilder();
            foreach (var item in entries)
            {
                ids.Append(item.ValueList[1] + "|");
            }

            loginContext.ServerInstance.DeleteEntry(entries.FirstOrDefault().FormName, ids.ToString(), 0);
        }

        /// <summary>
        /// Delete entris by query
        /// </summary>
        /// <!--William Wang-->
        /// <param name="qualification"> for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"  </param>
        public void DeleteEntryByQuery(string qualification)
        {
            if (String.IsNullOrWhiteSpace(qualification))
                throw new ArgumentNullException("qualification");

            T model = Activator.CreateInstance<T>();
            StringBuilder ids = new StringBuilder();

            var entrys = loginContext.ServerInstance.GetListEntryDescription(model.FormName, qualification);

            foreach (EntryDescription item in entrys)
            {
                ids.Append(item.EntryId + "|");
            }

            loginContext.ServerInstance.DeleteEntry(model.FormName, ids.ToString());

        }

        /// <summary>
        /// Set AR Entry by model
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entry">model</param>
        public void SetEntry(T entry)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            loginContext.ServerInstance.SetEntry(entry.FormName, entry.ValueList[1], entry.ValueList);

        }

        /// <summary>
        /// Set list entry
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entries">List Model</param>
        public void SetListEntry(IList<T> entries)
        {
            if (entries == null || entries.Count == 0)
                throw new ArgumentNullException("entries");

            foreach (T item in entries)
            {
                loginContext.ServerInstance.SetEntry(item.FormName, item.ValueList[1], item.ValueList);
            }
        }

        /// <summary>
        /// Set entris by query
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entry"> entry</param>
        /// <param name="qualification"> for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"  </param>
        /// <param name="getFormName">ARGetFormNameDelegate</param>
        /// <param name="noMatchOption">NoMatchOption</param>
        /// <param name="multiMatchOption">MultiMatchOption</param>
        /// <param name="useLocale">whether to use locale while getting the matched entry list </param>
        public void SetEntryByQuery(T entry, string qualification, Server.SetEntryByQuery_NoMatchOption noMatchOption =
            Server.SetEntryByQuery_NoMatchOption.NoAction,
            Server.SetEntryByQuery_MultiMatchOption multiMatchOption = Server.SetEntryByQuery_MultiMatchOption.ModifyAll)
        {
            if (entry == null)
                throw new ArgumentNullException("entry");
            if (String.IsNullOrWhiteSpace(qualification))
                throw new ArgumentNullException("qualification");

            loginContext.ServerInstance.SetEntryByQuery(entry.FormName, qualification,
                noMatchOption, multiMatchOption, entry.ValueList);

        }

        /// <summary>
        /// Get AR Entry by model, and indicate modelbinder、GetFormName
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entryID">entryID</param>
        public T GetEntry(string entryID)
        {
            if (String.IsNullOrEmpty(entryID))
                throw new ArgumentNullException("entryID");

            T entry = Activator.CreateInstance<T>();
            entry.ValueList = loginContext.ServerInstance.GetEntry(entry.FormName, entryID, null);
            return entry;

        }

        /// <summary>
        /// Get AR Entry by model, and indicate modelbinder、GetFormName
        /// </summary>
        /// <!--William Wang-->
        /// <param name="entryID">entryID</param>
        public T GetEntry(string entryID, IList<uint> ids)
        {
            if (String.IsNullOrWhiteSpace(entryID))
                throw new ArgumentNullException("entryID");
            if (null == ids || 0 == ids.Count)
                throw new ArgumentNullException("ids");

            if (!ids.Contains(1u)) ids.Add(1u);

            T entry = Activator.CreateInstance<T>();
            entry.ValueList = loginContext.ServerInstance.GetEntry(entry.FormName, entryID, GetFieldIdListFromIDs(ids));
            return entry;

        }

        /// <summary>
        /// Get entris by query
        /// </summary>
        /// <!--William Wang-->
        /// <param name="qualification"> for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"  </param>
        public IList<T> GetListEntry(string qualification, IList<uint> ids)
        {
            if (String.IsNullOrWhiteSpace(qualification))
                throw new ArgumentNullException("entryID");
            if (null == ids || 0 == ids.Count)
                throw new ArgumentNullException("ids");

            if (!ids.Contains(1u)) ids.Add(1u);

            T entry = Activator.CreateInstance<T>();
            List<T> listM = new List<T>();
            EntryFieldValueList entrys = null;
            entrys = loginContext.ServerInstance.GetListEntry(entry.FormName, qualification, GetEntryListFieldListFromIDs(ids));
            foreach (var item in entrys)
            {
                entry.ValueList = item.FieldValues;
                listM.Add(entry);
                entry = Activator.CreateInstance<T>();
            }
            return listM;
        }

        /// <summary>
        /// Get Paged Entries 
        /// </summary>
        /// <param name="qualification"> for example: "\'cChr_ProcessType\' LIKE \"%geGen%\" AND \'cInt_ApproveOrder\'=1004"  </param>
        /// <param name="ids"></param>
        /// <param name="pageIndex">Index Start </param>
        /// <param name="pageSize">Page Size</param>
        /// <param name="numMatches">Return Number</param>
        /// <param name="sortInfoList">Order by </param>
        /// <returns></returns>
        public IList<T> GetPagedEntry(string qualification, IList<uint> ids,
            uint pageIndex, uint pageSize, out int numMatches, ArrayList sortInfoList)
        {
            if (String.IsNullOrWhiteSpace(qualification))
                throw new ArgumentNullException("entryID");
            if (null == ids || 0 == ids.Count)
                throw new ArgumentNullException("ids");

            if (!ids.Contains(1u)) ids.Add(1u);

            T entry = Activator.CreateInstance<T>();
            EntryFieldValueList entrys = loginContext.ServerInstance.GetPagedEntry(entry.FormName, qualification,
                GetEntryListFieldListFromIDs(ids), pageIndex * pageSize, pageSize, out numMatches, sortInfoList);


            List<T> listM = new List<T>();

            foreach (var item in entrys)
            {
                entry.ValueList = item.FieldValues;
                listM.Add(entry);
                entry = Activator.CreateInstance<T>();
            }

            return listM;
        }

        private static EntryListFieldList GetEntryListFieldListFromIDs(IList<uint> ids)
        {
            EntryListFieldList fieldIDList = new EntryListFieldList();
            if (ids == null || ids.Count == 0)
            {
                fieldIDList = null;
            }
            else
            {
                foreach (var id in ids)
                {
                    fieldIDList.Add(new EntryListField(id));
                }
            }
            return fieldIDList;
        }

        private static FieldIdList GetFieldIdListFromIDs(IList<uint> ids)
        {
            FieldIdList fieldIDList = new FieldIdList();
            if (ids == null || ids.Count == 0)
            {
                fieldIDList = null;
            }
            else
            {
                foreach (var id in ids)
                {
                    fieldIDList.Add(id);
                }
            }
            return fieldIDList;
        }
    }

}
